home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / CD32 / CD32_Support / examples / SA_Examples / cd / CDTest / cd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-27  |  40.2 KB  |  1,589 lines

  1. /*
  2. **  cd.device Test
  3. **  Written by John J. Szucs
  4. **  Copyright © 1993-1999 Amiga, Inc.
  5. **  All Rights Reserved
  6. */
  7.  
  8. /*
  9. **  ANSI includes
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <math.h>
  16.  
  17. /*
  18. **  System includes
  19. */
  20.  
  21. #include <exec/types.h>
  22. #include <exec/memory.h>
  23. #include <exec/interrupts.h>
  24. #include <exec/io.h>
  25.  
  26. #include <utility/tagitem.h>
  27.  
  28. #include <dos/dos.h>
  29.  
  30. #include <devices/cd.h>
  31.  
  32. #include <devices/trackdisk.h>
  33.  
  34. #include <rexx/rxslib.h>
  35. #include <rexx/storage.h>
  36. #include <rexx/errors.h>
  37.  
  38. #include <clib/exec_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/rexxsyslib_protos.h>
  41. #include <clib/alib_protos.h>
  42.  
  43. /*
  44. **  Local includes
  45. */
  46.  
  47. #include "simplerexx.h"
  48. #include "cdtest.h"
  49.  
  50. /****** cd/cdAddChangeInt ******************************************
  51. *
  52. *   NAME
  53. *       cdAddChangeInt -- add change interrupt
  54. *
  55. *   SYNOPSIS
  56. *       result=cdAddChangeInt(rxMsg,args,error);
  57. *
  58. *       STRPTR cdAddChangeInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error);
  59. *
  60. *   FUNCTION
  61. *       Add change interrupt.
  62. *
  63. *   INPUTS
  64. *       rxMsg   -   ARexx message
  65. *       args    -   arguments from ARexx
  66. *       error   -   pointer to error value
  67. *
  68. *   RESULT
  69. *       *error  -   Error code (if any)
  70. *       result  -   result string
  71. *
  72. *   EXAMPLE
  73. *
  74. *   NOTES
  75. *
  76. *   BUGS
  77. *       Normal procedure for handling exec.library I/O requests
  78. *       requires that an I/O request be completed before it is
  79. *       re-used. However, for historical reasons, the *_ADDCHANGEINT
  80. *       and *_ADDFRAMEINT commands of trackdisk.device, scsi.device,
  81. *       and cd.device require the caller to send the I/O request
  82. *       to add the interrupt and re-use the I/O request (without
  83. *       calling exec.library/WaitIO()) with a *_REMCHANGEINT
  84. *       or *_REMFRAMEINT command to remove the interrupt.
  85. *
  86. *       This causes IOTorture hits and is, in my humble opinion,
  87. *       a Bad Thing(TM). However, it is apparently well beyond the
  88. *       point where this behavior could be changed.
  89. *
  90. *   SEE ALSO
  91. *       cdRemChangeInt
  92. *
  93. ******************************************************************************
  94. *
  95. */
  96.  
  97. STRPTR cdAddChangeInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  98. {
  99.  
  100.     /* Set-up disk change interrupt */
  101.     changeInterrupt.is_Node.ln_Name="CD Disk Change";
  102.     changeInterrupt.is_Data=(APTR) COOKIE_CHANGEINT;
  103.     changeInterrupt.is_Code=(void (*)()) changeInterruptCode;
  104.     changeIntCall=changeIntBadData=0L;
  105.  
  106.     /* Add disk change interrupt */
  107.     cdRequest->io_Command=CD_ADDCHANGEINT;
  108.     cdRequest->io_Length=sizeof(changeInterrupt);
  109.     cdRequest->io_Data=&changeInterrupt;
  110.     SendIO(cdRequest);
  111.  
  112.     /* Return w/o result */
  113.     return(NULL);
  114.  
  115. }
  116.  
  117. /****** cd/cdAddFrameInt ******************************************
  118. *
  119. *   NAME
  120. *       cdAddChangeInt -- add frame interrupt
  121. *
  122. *   SYNOPSIS
  123. *       result=cdAddFrameInt(rxMsg,args,error);
  124. *
  125. *       STRPTR cdAddFrameInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error);
  126. *
  127. *   FUNCTION
  128. *       Add frame interrupt.
  129. *
  130. *   INPUTS
  131. *       rxMsg   -   ARexx message
  132. *       args    -   arguments from ARexx
  133. *       error   -   pointer to error value
  134. *
  135. *   RESULT
  136. *       *error  -   Error code (if any)
  137. *       result  -   result string
  138. *
  139. *   EXAMPLE
  140. *
  141. *   NOTES
  142. *
  143. *   BUGS
  144. *       Normal procedure for handling exec.library I/O requests
  145. *       requires that an I/O request be completed before it is
  146. *       re-used. However, for historical reasons, the *_ADDCHANGEINT
  147. *       and *_ADDFRAMEINT commands of trackdisk.device, scsi.device,
  148. *       and cd.device require the caller to send the I/O request
  149. *       to add the interrupt and re-use the I/O request (without
  150. *       calling exec.library/WaitIO()) with a *_REMCHANGEINT
  151. *       or *_REMFRAMEINT command to remove the interrupt.
  152. *
  153. *       This causes IOTorture hits and is, in my humble opinion,
  154. *       a Bad Thing(TM). However, it is apparently well beyond the
  155. *       point where this behavior could be changed.
  156. *
  157. *   SEE ALSO
  158. *       cdRemFrameInt
  159. *
  160. ******************************************************************************
  161. *
  162. */
  163.  
  164. STRPTR cdAddFrameInt(struct RexxMsg *rxMsg,STRPTR  args,LONG *error)
  165. {
  166.  
  167.     if (debugMode) {
  168.         printf("Initializing frameInterrupt\n");
  169.     }
  170.  
  171.     /* Set-up frame interrupt */
  172.     frameInterrupt.is_Node.ln_Pri=0;
  173.     frameInterrupt.is_Node.ln_Name="CD Frame";
  174.     frameInterrupt.is_Data=(APTR) COOKIE_FRAMEINT;
  175.     frameInterrupt.is_Code=(void (*)()) frameInterruptCode;
  176.     frameIntCall=frameIntBadData=0L;
  177.  
  178.     if (debugMode) {
  179.         printf("frameInterrupt initialized: is_Data=$%08lx, is_Code=$%08lx\n",
  180.             frameInterrupt.is_Data,frameInterrupt.is_Code);
  181.     }
  182.  
  183.     /* Add frame interrupt */
  184.     cdRequest->io_Command=CD_ADDFRAMEINT;
  185.     cdRequest->io_Length=sizeof(frameInterrupt);
  186.     cdRequest->io_Data=&frameInterrupt;
  187.     SendIO(cdRequest);
  188.     if (debugMode) {
  189.         printf("CD_ADDFRAMEINT good\n");
  190.     }
  191.  
  192.     /* Return w/o result */
  193.     return(NULL);
  194.  
  195. }
  196.  
  197. STRPTR cdAttenuate(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  198. {
  199.  
  200.     static struct options {
  201.         LONG *duration;
  202.         LONG *target;
  203.     } options;
  204.     struct RDArgs *rdArgs;
  205.  
  206.     BYTE ioError;
  207.  
  208.     STRPTR result=NULL;
  209.  
  210.     /* Parse arguments */
  211.     rdArgs=obtainArgs(args,"DURATION/N/A,TARGET/N/A",
  212.         &options,sizeof(options));
  213.     if (!rdArgs) {
  214.         *error=RC_ERROR;
  215.         return(NULL);
  216.     }
  217.  
  218.     cdRequest->io_Command=CD_ATTENUATE;
  219.     cdRequest->io_Length=*options.duration;
  220.     cdRequest->io_Offset=*options.target;
  221.     if (noCD) {
  222.         ioError=-1;
  223.     } else {
  224.         ioError=DoIO(cdRequest);
  225.     }
  226.     if (ioError) {
  227.         if (debugMode) {
  228.             printf("CD_ATTENUATE I/O error %d\n",ioError);
  229.         }
  230.         *error=RC_ERROR;
  231.         result=NULL;
  232.     } else {
  233.         /* Return current volume */
  234.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  235.         result=rexxResult;
  236.     }
  237.  
  238.     /* Free argument parsing structure */
  239.     releaseArgs(rdArgs);
  240.  
  241.     /* Return result */
  242.     return(result);
  243.  
  244. }
  245.  
  246. STRPTR cdChangeNum(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  247. {
  248.  
  249.     BYTE ioError;
  250.  
  251.     STRPTR result=NULL;
  252.  
  253.     cdRequest->io_Command=CD_CHANGENUM;
  254.     if (noCD) {
  255.         ioError=-1;
  256.     } else {
  257.         ioError=DoIO(cdRequest);
  258.     }
  259.     if (ioError) {
  260.         if (debugMode) {
  261.             printf("CD_CHANGENUM I/O error %d\n",ioError);
  262.         }
  263.         *error=RC_ERROR;
  264.         result=NULL;
  265.     } else {
  266.         /* Return disk-change counter */
  267.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  268.         result=rexxResult;
  269.     }
  270.  
  271.     /* Return result */
  272.     return(result);
  273.  
  274. }
  275.  
  276. STRPTR cdChangeState(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  277. {
  278.  
  279.                     BYTE ioError;
  280.  
  281.     STRPTR result=NULL;
  282.  
  283.     cdRequest->io_Command=CD_CHANGESTATE;
  284.     if (noCD) {
  285.         ioError=-1;
  286.     } else {
  287.         ioError=DoIO(cdRequest);
  288.     }
  289.     if (ioError) {
  290.         if (debugMode) {
  291.             printf("CD_CHANGESTATE I/O error %d\n",ioError);
  292.         }
  293.         *error=RC_ERROR;
  294.         result=NULL;
  295.     } else {
  296.         /* Return disk-change state */
  297.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  298.         result=rexxResult;
  299.     }
  300.  
  301.     /* Return result */
  302.     return(result);
  303.  
  304. }
  305.  
  306. /*
  307.  *  CD_CONFIG TAGCD_* definitions conflict with standard system tag definitions
  308.  *  in utility/utility.h.
  309.  *
  310.  *  As a result, this function is implemented in a less than optimal manner.
  311.  *
  312.  */
  313.  
  314.  
  315. STRPTR cdConfig(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  316. {
  317.  
  318.     static struct options {
  319.         LONG *playSpeed;
  320.         LONG *readSpeed;
  321.         LONG *readXLSpeed;
  322.         LONG *sectorSize;
  323.         LONG xlECC;
  324.         LONG noXLECC;
  325.         LONG ejectReset;
  326.         LONG noEjectReset;
  327.     } options;
  328.     struct RDArgs *rdArgs;
  329.  
  330.     BYTE ioError;
  331.  
  332.     STRPTR result=NULL;
  333.  
  334.     static struct TagItem configTags[CDCONFIG_MAXTAGS];
  335.     int thisTag=0;
  336.  
  337.     /* Parse arguments */
  338.     rdArgs=obtainArgs(args,
  339.        "PLAYSPEED/N,READSPEED/N,READXLSPEED/N,SECTORSIZE/N,XLECC/S,NOXLECC/S,EJECTRESET/S,NOEJECTRESET/S",
  340.        &options,sizeof(options));
  341.     if (!rdArgs) {
  342.        *error=RC_ERROR;
  343.        return(NULL);
  344.     }
  345.  
  346.     /* Play speed */
  347.     if (options.playSpeed) {
  348.         configTags[thisTag].ti_Tag=TAGCD_PLAYSPEED;
  349.         configTags[thisTag].ti_Data=*options.playSpeed;
  350.         thisTag++;
  351.     }
  352.     if (debugMode) {
  353.         printf(options.playSpeed?"PlaySpeed=%d\n":"PlaySpeed=Not specified\n",
  354.             options.playSpeed?*options.playSpeed:NULL);
  355.     }
  356.  
  357.     /* Read speed */
  358.     if (options.readSpeed) {
  359.         configTags[thisTag].ti_Tag=TAGCD_READSPEED;
  360.         configTags[thisTag].ti_Data=*options.readSpeed;
  361.         thisTag++;
  362.     }
  363.     if (debugMode) {
  364.         printf(options.readSpeed?"ReadSpeed=%d\n":"ReadSpeed=Not specified\n",
  365.             options.readSpeed?*options.readSpeed:NULL);
  366.     }
  367.  
  368.     /* XL Read speed */
  369.     if (options.readXLSpeed) {
  370.         configTags[thisTag].ti_Tag=TAGCD_READSPEED;
  371.         configTags[thisTag].ti_Data=*options.readXLSpeed;
  372.         thisTag++;
  373.     }
  374.     if (debugMode) {
  375.         printf(options.readXLSpeed?"ReadXLSpeed=%d\n":"ReadXLSpeed=Not specified\n",
  376.             options.readXLSpeed?*options.readXLSpeed:NULL);
  377.     }
  378.  
  379.     /* Sector size */
  380.     if (options.sectorSize) {
  381.         configTags[thisTag].ti_Tag=TAGCD_SECTORSIZE;
  382.         configTags[thisTag].ti_Data=*options.sectorSize;
  383.         thisTag++;
  384.     }
  385.     if (debugMode) {
  386.         printf(options.sectorSize?"SectorSize=%d\n":"SectorSize=Not specified\n",
  387.             options.sectorSize?*options.sectorSize:NULL);
  388.     }
  389.  
  390.     /* XL ECC */
  391.     if (options.xlECC|options.noXLECC) {
  392.         configTags[thisTag].ti_Tag=TAGCD_XLECC;
  393.         configTags[thisTag].ti_Data=options.xlECC?TRUE:FALSE;
  394.         thisTag++;
  395.     }
  396.     if (debugMode) {
  397.         printf(options.xlECC?"XLECC=%d\n":"XLECC=Not specified\n",
  398.             options.xlECC?"TRUE":"FALSE");
  399.     }
  400.  
  401.     /* Reset on eject */
  402.     if (options.ejectReset|options.noEjectReset) {
  403.         configTags[thisTag].ti_Tag=TAGCD_EJECTRESET;
  404.         configTags[thisTag].ti_Data=
  405.             (options.ejectReset&options.noEjectReset)?0xFFFFFFFF:(options.ejectReset?TRUE:FALSE);
  406.         thisTag++;
  407.     }
  408.     if (debugMode) {
  409.         printf(options.ejectReset?"EjectReset=%d\n":"EjectReset=Not specified\n",
  410.             options.ejectReset?"TRUE":"FALSE");
  411.     }
  412.  
  413.     /* Terminate tag array */
  414.     configTags[thisTag].ti_Tag=TAG_DONE;
  415.  
  416.     cdRequest->io_Command=CD_CONFIG;
  417.     cdRequest->io_Data=configTags;
  418.     cdRequest->io_Length=0;
  419.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  420.     if (ioError) {
  421.         if (debugMode) {
  422.             printf("CD_CONFIG I/O error %d\n",ioError);
  423.         }
  424.         *error=RC_ERROR;
  425.     }
  426.  
  427.     /* Free argument parsing structure */
  428.     releaseArgs(rdArgs);
  429.  
  430.     /* Return result */
  431.     return(result);
  432.  
  433. }
  434.  
  435. STRPTR cdEject(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  436. {
  437.  
  438.     static struct options {
  439.         LONG open;
  440.         LONG close;
  441.     } options;
  442.     struct RDArgs *rdArgs;
  443.  
  444.     BYTE ioError;
  445.  
  446.     STRPTR result=NULL;
  447.  
  448.     /* Parse arguments */
  449.     rdArgs=obtainArgs(args,"OPEN/S,CLOSE/S",
  450.         &options,sizeof(options));
  451.     if (!rdArgs) {
  452.         *error=RC_ERROR;
  453.         return(NULL);
  454.     }
  455.  
  456.     cdRequest->io_Command=CD_EJECT;
  457.     cdRequest->io_Length=options.open?1:(options.close?0:-1);
  458.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  459.     if (ioError) {
  460.         if (debugMode) {
  461.             printf("CD_EJECT I/O error %d\n",ioError);
  462.         }
  463.         *error=RC_ERROR;
  464.         result=NULL;
  465.     } else {
  466.         /* Return current door state */
  467.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  468.         result=rexxResult;
  469.     }
  470.  
  471.     /* Free argument parsing structure */
  472.     releaseArgs(rdArgs);
  473.  
  474.     /* Return result */
  475.     return(result);
  476.  
  477. }
  478.  
  479. STRPTR cdGetGeometry(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  480. {
  481.  
  482.     static struct options {
  483.         STRPTR stem;
  484.     } options;
  485.     struct RDArgs *rdArgs;
  486.  
  487.     BYTE ioError;
  488.  
  489.     struct DriveGeometry driveGeometry;
  490.  
  491.     /* Parse arguments */
  492.     rdArgs=obtainArgs(args,"STEM/A",&options,sizeof(options));
  493.     if (!rdArgs) {
  494.         *error=RC_ERROR;
  495.         return(NULL);
  496.     }
  497.  
  498.     /* Fetch drive geometry */
  499.     cdRequest->io_Command=CD_GETGEOMETRY;
  500.     cdRequest->io_Length=sizeof(driveGeometry);
  501.     cdRequest->io_Data=&driveGeometry;
  502.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  503.     if (ioError) {
  504.         if (debugMode) {
  505.             printf("CD_GETGEOMETRY I/O error %d\n",ioError);
  506.         }
  507.         *error=RC_ERROR;
  508.     } else {
  509.  
  510.         /* Return drive geometry in ARexx stem variable */
  511.         setStemVarInt(rxMsg,options.stem,"SectorSize",
  512.             driveGeometry.dg_SectorSize);
  513.         setStemVarInt(rxMsg,options.stem,"TotalSectors",
  514.             driveGeometry.dg_TotalSectors);
  515.         setStemVarInt(rxMsg,options.stem,"Cylinders",
  516.             driveGeometry.dg_Cylinders);
  517.         setStemVarInt(rxMsg,options.stem,"CylSectors",
  518.             driveGeometry.dg_CylSectors);
  519.         setStemVarInt(rxMsg,options.stem,"Heads",
  520.             driveGeometry.dg_Heads);
  521.         setStemVarInt(rxMsg,options.stem,"TrackSectors",
  522.             driveGeometry.dg_TrackSectors);
  523.         setStemVarInt(rxMsg,options.stem,"BufMemType",
  524.             driveGeometry.dg_BufMemType);
  525.         setStemVarInt(rxMsg,options.stem,"DeviceType",
  526.             driveGeometry.dg_DeviceType);
  527.         setStemVarInt(rxMsg,options.stem,"Removable",
  528.             driveGeometry.dg_Flags&DGF_REMOVABLE);
  529.  
  530.     }
  531.  
  532.     /* Free argument parsing structure */
  533.     releaseArgs(rdArgs);
  534.  
  535.     /* Return */
  536.     return(NULL);
  537.  
  538. }
  539.  
  540. STRPTR cdInfo(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  541. {
  542.  
  543.     static struct options {
  544.         STRPTR stem;
  545.     } options;
  546.     struct RDArgs *rdArgs;
  547.  
  548.     BYTE ioError;
  549.  
  550.     STRPTR result=NULL;
  551.  
  552.     struct CDInfo cdInfo;
  553.  
  554.     /* Parse arguments */
  555.     rdArgs=obtainArgs(args,"STEM/A",&options,sizeof(options));
  556.     if (!rdArgs) {
  557.         *error=RC_ERROR;
  558.         return(NULL);
  559.     }
  560.  
  561.     /* Fetch device information */
  562.     cdRequest->io_Command=CD_INFO;
  563.     cdRequest->io_Length=sizeof(cdInfo);
  564.     cdRequest->io_Data=&cdInfo;
  565.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  566.     if (ioError) {
  567.         if (debugMode) {
  568.             printf("CD_INFO I/O error %d\n",ioError);
  569.         }
  570.         *error=RC_ERROR;
  571.     } else {
  572.  
  573.         /* Return device information in ARexx stem variable */
  574.         setStemVarInt(rxMsg,options.stem,"PlaySpeed",
  575.             cdInfo.PlaySpeed);
  576.         if (debugMode) {
  577.             printf("PlaySpeed=%d\n",cdInfo.PlaySpeed);
  578.         }
  579.         setStemVarInt(rxMsg,options.stem,"ReadSpeed",
  580.             cdInfo.ReadSpeed);
  581.         if (debugMode) {
  582.             printf("ReadSpeed=%d\n",cdInfo.ReadSpeed);
  583.         }
  584.         setStemVarInt(rxMsg,options.stem,"ReadXLSpeed",
  585.             cdInfo.ReadXLSpeed);
  586.         if (debugMode) {
  587.             printf("ReadXLSpeed=%d\n",cdInfo.ReadXLSpeed);
  588.         }
  589.         setStemVarInt(rxMsg,options.stem,"SectorSize",
  590.             cdInfo.SectorSize);
  591.         if (debugMode) {
  592.             printf("SectorSize=%d\n",cdInfo.SectorSize);
  593.         }
  594.         setStemVarInt(rxMsg,options.stem,"XLECC",
  595.             cdInfo.XLECC);
  596.         if (debugMode) {
  597.             printf("XLECC=%d\n",cdInfo.XLECC);
  598.         }
  599.         setStemVarInt(rxMsg,options.stem,"EjectReset",
  600.             cdInfo.EjectReset);
  601.         if (debugMode) {
  602.             printf("EjectReset=%d\n",cdInfo.EjectReset);
  603.         }
  604.         setStemVarInt(rxMsg,options.stem,"MaxSpeed",
  605.             cdInfo.MaxSpeed);
  606.         if (debugMode) {
  607.             printf("MaxSpeed=%d\n",cdInfo.MaxSpeed);
  608.         }
  609.         setStemVarInt(rxMsg,options.stem,"AudioPrecision",
  610.             cdInfo.AudioPrecision);
  611.         if (debugMode) {
  612.             printf("AudioPrecision=%d\n",cdInfo.AudioPrecision);
  613.         }
  614.         if (debugMode) {
  615.             printf("Status=$%04x\n",cdInfo.Status);
  616.         }
  617.         setStemVarInt(rxMsg,options.stem,"Closed",
  618.             cdInfo.Status&CDSTSF_CLOSED);
  619.         if (debugMode) {
  620.             printf("Closed=%d\n",cdInfo.Status&CDSTSF_CLOSED);
  621.         }
  622.         setStemVarInt(rxMsg,options.stem,"Disk",
  623.             cdInfo.Status&CDSTSF_DISK);
  624.         if (debugMode) {
  625.             printf("Disk=%d\n",cdInfo.Status&CDSTSF_DISK);
  626.         }
  627.         setStemVarInt(rxMsg,options.stem,"Spin",
  628.             cdInfo.Status&CDSTSF_SPIN);
  629.         if (debugMode) {
  630.             printf("Spin=%d\n",cdInfo.Status&CDSTSF_SPIN);
  631.         }
  632.         setStemVarInt(rxMsg,options.stem,"TOC",
  633.             cdInfo.Status&CDSTSF_TOC);
  634.         if (debugMode) {
  635.             printf("TOC=%d\n",cdInfo.Status&CDSTSF_TOC);
  636.         }
  637.         setStemVarInt(rxMsg,options.stem,"CDROM",
  638.             cdInfo.Status&CDSTSF_CDROM);
  639.         if (debugMode) {
  640.             printf("CDROM=%d\n",cdInfo.Status&CDSTSF_CDROM);
  641.         }
  642.         setStemVarInt(rxMsg,options.stem,"Playing",
  643.             cdInfo.Status&CDSTSF_PLAYING);
  644.         if (debugMode) {
  645.             printf("Playing=%d\n",cdInfo.Status&CDSTSF_PLAYING);
  646.         }
  647.         setStemVarInt(rxMsg,options.stem,"Paused",
  648.             cdInfo.Status&CDSTSF_PAUSED);
  649.         if (debugMode) {
  650.             printf("Paused=%d\n",cdInfo.Status&CDSTSF_PAUSED);
  651.         }
  652.         setStemVarInt(rxMsg,options.stem,"Search",
  653.             cdInfo.Status&CDSTSF_SEARCH);
  654.         if (debugMode) {
  655.             printf("Search=%d\n",cdInfo.Status&CDSTSF_SEARCH);
  656.         }
  657.         setStemVarInt(rxMsg,options.stem,"Direction",
  658.             cdInfo.Status&CDSTSF_DIRECTION);
  659.         if (debugMode) {
  660.             printf("Direction=%d\n",cdInfo.Status&CDSTSF_DIRECTION);
  661.         }
  662.  
  663.     }
  664.  
  665.     /* Free argument parsing structure */
  666.     releaseArgs(rdArgs);
  667.  
  668.     /* Return */
  669.     return(result);
  670.  
  671. }
  672.  
  673. STRPTR cdMotor(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  674. {
  675.  
  676.     static struct options {
  677.         LONG on;
  678.         LONG off;
  679.     } options;
  680.     struct RDArgs *rdArgs;
  681.  
  682.     BYTE ioError;
  683.  
  684.     STRPTR result=NULL;
  685.  
  686.     /* Parse arguments */
  687.     rdArgs=obtainArgs(args,"ON/S,OFF/S",
  688.         &options,sizeof(options));
  689.     if (!rdArgs) {
  690.         *error=RC_ERROR;
  691.         return(NULL);
  692.     }
  693.  
  694.     cdRequest->io_Command=CD_MOTOR;
  695.     cdRequest->io_Length=options.on?1:(options.off?0:-1);
  696.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  697.     if (ioError) {
  698.         if (debugMode) {
  699.             printf("CD_EJECT I/O error %d\n",ioError);
  700.         }
  701.         *error=RC_ERROR;
  702.         result=NULL;
  703.     } else {
  704.         /* Return current motor state */
  705.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  706.         result=rexxResult;
  707.     }
  708.  
  709.     /* Free argument parsing structure */
  710.     releaseArgs(rdArgs);
  711.  
  712.     /* Return result */
  713.     return(result);
  714.  
  715. }
  716.  
  717. STRPTR cdPause(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  718. {
  719.  
  720.     static struct options {
  721.         LONG on;
  722.         LONG off;
  723.     } options;
  724.     struct RDArgs *rdArgs;
  725.  
  726.     BYTE ioError;
  727.  
  728.     STRPTR result=NULL;
  729.  
  730.     /* Parse arguments */
  731.     rdArgs=obtainArgs(args,"ON/S,OFF/S",
  732.         &options,sizeof(options));
  733.     if (!rdArgs) {
  734.         *error=RC_ERROR;
  735.         return(NULL);
  736.     }
  737.  
  738.     cdRequest->io_Command=CD_PAUSE;
  739.     cdRequest->io_Length=options.on?1:(options.off?0:-1);
  740.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  741.     if (ioError) {
  742.         if (debugMode) {
  743.             printf("CD_PAUSE I/O error %d\n",ioError);
  744.         }
  745.         *error=RC_ERROR;
  746.         result=NULL;
  747.     } else {
  748.  
  749.         /* Return pause state */
  750.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  751.         result=rexxResult;
  752.  
  753.     }
  754.  
  755.     /* Free argument parsing structure */
  756.     releaseArgs(rdArgs);
  757.  
  758.     /* Return result */
  759.     return(result);
  760.  
  761. }
  762.  
  763. STRPTR cdPlayLSN(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  764. {
  765.  
  766.     static struct options {
  767.         LONG *start;
  768.         LONG *length;
  769.     } options;
  770.     struct RDArgs *rdArgs;
  771.  
  772.     BYTE ioError;
  773.  
  774.     STRPTR result=NULL;
  775.  
  776.     /* Parse arguments */
  777.     rdArgs=obtainArgs(args,"START/N/A,LENGTH/N/A",&options,sizeof(options));
  778.     if (!rdArgs) {
  779.         *error=RC_ERROR;
  780.         return(NULL);
  781.     }
  782.  
  783.     /* Play audio */
  784.     cdRequest->io_Command=CD_PLAYLSN;
  785.     cdRequest->io_Length=*options.length;
  786.     cdRequest->io_Offset=*options.start;
  787.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  788.     if (ioError) {
  789.         if (debugMode) {
  790.             printf("CD_PLAYLSN I/O error %d\n",ioError);
  791.         }
  792.         *error=RC_ERROR;
  793.         result=NULL;
  794.     } else {
  795.         result=NULL;
  796.     }
  797.  
  798.     /* Free argument parsing structure */
  799.     releaseArgs(rdArgs);
  800.  
  801.     /* Return result */
  802.     return(result);
  803.  
  804. }
  805.  
  806. STRPTR cdPlayMSF(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  807. {
  808.  
  809.     static struct options {
  810.         STRPTR start;
  811.         STRPTR length;
  812.     } options;
  813.     struct RDArgs *rdArgs;
  814.     ULONG startMSF, lengthMSF;
  815.  
  816.     BYTE ioError;
  817.  
  818.     STRPTR result=NULL;
  819.  
  820.     /* Parse arguments */
  821.     rdArgs=obtainArgs(args,"START/A,LENGTH/A",&options,sizeof(options));
  822.     if (!rdArgs) {
  823.         *error=RC_ERROR;
  824.         return(NULL);
  825.     }
  826.     if (debugMode) {
  827.         printf("cdPlayMSF -- start=%s, length=%s\n",options.start,
  828.             options.length);
  829.     }
  830.     startMSF=strToMSF(options.start);
  831.     lengthMSF=strToMSF(options.length);
  832.     if (debugMode) {
  833.         printf("cdPlayMSF -- start=$%08lx, length=$%08lx\n",startMSF,lengthMSF);
  834.     }
  835.  
  836.     /* Play audio */
  837.     cdRequest->io_Command=CD_PLAYMSF;
  838.     cdRequest->io_Length=lengthMSF;
  839.     cdRequest->io_Offset=startMSF;
  840.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  841.     if (ioError) {
  842.         if (debugMode) {
  843.             printf("CD_PLAYMSF I/O error %d\n",ioError);
  844.         }
  845.         *error=RC_ERROR;
  846.         result=NULL;
  847.     } else {
  848.         result=NULL;
  849.     }
  850.  
  851.     /* Free argument parsing structure */
  852.     releaseArgs(rdArgs);
  853.  
  854.     /* Return result */
  855.     return(result);
  856.  
  857. }
  858.  
  859. STRPTR cdPlayTrack(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  860. {
  861.  
  862.     static struct options {
  863.         LONG *start;
  864.         LONG *length;
  865.     } options;
  866.     struct RDArgs *rdArgs;
  867.  
  868.     BYTE ioError;
  869.  
  870.     STRPTR result=NULL;
  871.  
  872.     /* Parse arguments */
  873.     rdArgs=obtainArgs(args,"START/N/A,LENGTH/N/A",&options,sizeof(options));
  874.     if (!rdArgs) {
  875.         *error=RC_ERROR;
  876.         return(NULL);
  877.     }
  878.  
  879.     /* Play track */
  880.     cdRequest->io_Command=CD_PLAYTRACK;
  881.     cdRequest->io_Length=*options.length;
  882.     cdRequest->io_Offset=*options.start;
  883.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  884.     if (ioError) {
  885.         if (debugMode) {
  886.             printf("CD_PLAYTRACK I/O error %d\n",ioError);
  887.         }
  888.         *error=RC_ERROR;
  889.         result=NULL;
  890.     } else {
  891.         result=NULL;
  892.     }
  893.  
  894.     /* Free argument parsing structure */
  895.     releaseArgs(rdArgs);
  896.  
  897.     /* Return result */
  898.     return(result);
  899.  
  900.  
  901. }
  902.  
  903. STRPTR cdProtStatus(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  904. {
  905.  
  906.     BYTE ioError;
  907.  
  908.     STRPTR result=NULL;
  909.  
  910.     cdRequest->io_Command=CD_PROTSTATUS;
  911.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  912.     if (ioError) {
  913.         if (debugMode) {
  914.             printf("CD_PROTSTATUS I/O error %d\n",ioError);
  915.         }
  916.         *error=RC_ERROR;
  917.         result=NULL;
  918.     } else {
  919.         /* Return protection status */
  920.         bsprintf(rexxResult,"%ld",cdRequest->io_Actual);
  921.         result=rexxResult;
  922.     }
  923.  
  924.     /* Return result */
  925.     return(result);
  926.  
  927. }
  928.  
  929. STRPTR cdQCodeLSN(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  930. {
  931.  
  932.     static struct options {
  933.         STRPTR stem;
  934.     } options;
  935.     struct RDArgs *rdArgs;
  936.  
  937.     BYTE ioError;
  938.  
  939.     struct QCode qCode;
  940.  
  941.     /* Parse arguments */
  942.     rdArgs=obtainArgs(args,"STEM/A",&options,sizeof(options));
  943.     if (!rdArgs) {
  944.         *error=RC_ERROR;
  945.         return(NULL);
  946.     }
  947.  
  948.     /* Fetch Q-Code */
  949.     cdRequest->io_Command=CD_QCODELSN;
  950.     cdRequest->io_Length=0;
  951.     cdRequest->io_Data=&qCode;
  952.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  953.     if (ioError) {
  954.         if (debugMode) {
  955.             printf("CD_QCODELSN I/O error %d\n",ioError);
  956.         }
  957.         *error=RC_ERROR;
  958.     } else {
  959.  
  960.         /* Return QCode data in ARexx stem variable */
  961.         setStemVarInt(rxMsg,options.stem,"CtlAdr",qCode.CtlAdr);
  962.         setStemVarInt(rxMsg,options.stem,"Track",qCode.Track);
  963.         setStemVarInt(rxMsg,options.stem,"Index",qCode.Index);
  964.         setStemVarInt(rxMsg,options.stem,"Zero",qCode.Zero);
  965.         setStemVarInt(rxMsg,options.stem,"TrackPosition",
  966.             qCode.TrackPosition.LSN);
  967.         setStemVarInt(rxMsg,options.stem,"DiskPosition",
  968.             qCode.DiskPosition.LSN);
  969.  
  970.     }
  971.  
  972.     /* Free argument parsing structure */
  973.     releaseArgs(rdArgs);
  974.  
  975.     /* Return */
  976.     return(NULL);
  977.  
  978. }
  979.  
  980. STRPTR cdQCodeMSF(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  981. {
  982.  
  983.     static struct options {
  984.         STRPTR stem;
  985.     } options;
  986.     struct RDArgs *rdArgs;
  987.  
  988.     BYTE ioError;
  989.  
  990.     STRPTR result=NULL;
  991.  
  992.     struct QCode qCode;
  993.  
  994.     /* Parse arguments */
  995.     rdArgs=obtainArgs(args,"STEM/A",&options,sizeof(options));
  996.     if (!rdArgs) {
  997.         *error=RC_ERROR;
  998.         return(NULL);
  999.     }
  1000.  
  1001.     /* Fetch Q-Code */
  1002.     cdRequest->io_Command=CD_QCODEMSF;
  1003.     cdRequest->io_Length=0;
  1004.     cdRequest->io_Data=&qCode;
  1005.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1006.     if (ioError) {
  1007.         if (debugMode) {
  1008.             printf("CD_QCODEMSF I/O error %d\n",ioError);
  1009.         }
  1010.         *error=RC_ERROR;
  1011.         result=NULL;
  1012.     } else {
  1013.  
  1014.         /* Return QCode data in ARexx stem variable */
  1015.         setStemVarInt(rxMsg,options.stem,"CtlAdr",qCode.CtlAdr);
  1016.         setStemVarInt(rxMsg,options.stem,"Track",qCode.Track);
  1017.         setStemVarInt(rxMsg,options.stem,"Index",qCode.Index);
  1018.         setStemVarInt(rxMsg,options.stem,"Zero",qCode.Zero);
  1019.         setStemVarInt(rxMsg,options.stem,"TrackPosition.Minute",
  1020.             qCode.TrackPosition.MSF.Minute);
  1021.         setStemVarInt(rxMsg,options.stem,"TrackPosition.Second",
  1022.             qCode.TrackPosition.MSF.Second);
  1023.         setStemVarInt(rxMsg,options.stem,"TrackPosition.Frame",
  1024.             qCode.TrackPosition.MSF.Frame);
  1025.         setStemVarInt(rxMsg,options.stem,"DiskPosition.Minute",
  1026.             qCode.DiskPosition.MSF.Minute);
  1027.         setStemVarInt(rxMsg,options.stem,"DiskPosition.Second",
  1028.             qCode.DiskPosition.MSF.Second);
  1029.         setStemVarInt(rxMsg,options.stem,"DiskPosition.Frame",
  1030.             qCode.DiskPosition.MSF.Frame);
  1031.  
  1032.     }
  1033.  
  1034.     /* Free argument parsing structure */
  1035.     releaseArgs(rdArgs);
  1036.  
  1037.     /* Return */
  1038.     return(result);
  1039.  
  1040. }
  1041.  
  1042. STRPTR cdRead(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1043. {
  1044.  
  1045.     static struct options {
  1046.         LONG *offset;
  1047.         LONG *length;
  1048.         LONG byteVerify;
  1049.         LONG wordVerify;
  1050.         LONG offsetVerify;
  1051.         LONG *start;
  1052.     } options;
  1053.     struct RDArgs *rdArgs;
  1054.  
  1055.     BYTE ioError;
  1056.  
  1057.     UBYTE *buffer;
  1058.  
  1059.     /* Parse arguments */
  1060.     if (debugMode) {
  1061.         printf("cdRead: Calling obtainArgs()\n");
  1062.     }
  1063.     rdArgs=obtainArgs(args,
  1064.         "OFFSET/N/A,LENGTH/N/A,BV=BYTEVERIFY/S,WV=WORDVERIFY/S,OV=OFFSETVERIFY/S,START/N",
  1065.         &options,sizeof(options));
  1066.     if (!rdArgs) {
  1067.         if (debugMode) {
  1068.             printf("cdRead: obtainArgs() failed\n");
  1069.         }
  1070.         *error=RC_ERROR;
  1071.         return(NULL);
  1072.     }
  1073.     if (debugMode) {
  1074.         printf("cdRead: obtainArgs() good\n");
  1075.     }
  1076.  
  1077.     /* Allocate buffer */
  1078.     buffer=AllocVec(*options.length,NULL);
  1079.     if (!buffer) {
  1080.         if (debugMode) {
  1081.             printf("cdRead: Buffer allocation failed\n");
  1082.         }
  1083.         *error=RC_ERROR;
  1084.         return(NULL);
  1085.     }
  1086.     if (debugMode) {
  1087.         printf("cdRead: Allocated %lu-byte buffer at $%08lx\n",
  1088.             *options.length,buffer);
  1089.     }
  1090.  
  1091.     /* Read data */
  1092.     cdRequest->io_Command=CD_READ;
  1093.     cdRequest->io_Data=buffer;
  1094.     cdRequest->io_Length=*options.length;
  1095.     cdRequest->io_Offset=*options.offset;
  1096.     if (debugMode) {
  1097.         printf("cdRead: Calling CD_READ\n");
  1098.     }
  1099.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1100.     if (debugMode) {
  1101.         printf("cdRead: CD_READ returned %d\n",ioError);
  1102.     }
  1103.     if (ioError) {
  1104.         if (debugMode) {
  1105.             printf("CD_READ I/O error %d\n",ioError);
  1106.         }
  1107.         *error=RC_ERROR;
  1108.     } else {
  1109.         /* Verify byte pattern */
  1110.         if (options.byteVerify) {
  1111.             *error=
  1112.                 byteVerify(buffer,*options.length,
  1113.                     options.start?*options.start:0)?
  1114.                 RC_OK:RC_WARN;
  1115.         }
  1116.         /* Verify word pattern */
  1117.         if (options.wordVerify) {
  1118.             *error=
  1119.                 wordVerify(buffer,*options.length,
  1120.                     options.start?*options.start:0)?
  1121.                 RC_OK:RC_WARN;
  1122.         }
  1123.         /* Verify offset pattern */
  1124.         if (options.offsetVerify) {
  1125.             if (debugMode) {
  1126.                 printf("cdRead: Verifying offset pattern\n");
  1127.             }
  1128.             *error=
  1129.                 offsetVerify(buffer,*options.length,
  1130.                     options.start?*options.start:0)?
  1131.                 RC_OK:RC_WARN;
  1132.             if (debugMode) {
  1133.                 printf("cdRead: Offset verify status %d\n",*error);
  1134.             }
  1135.         }
  1136.  
  1137.     }
  1138.  
  1139.     /* Free buffer */
  1140.     FreeVec(buffer);
  1141.  
  1142.     /* Free argument parsing structure */
  1143.     releaseArgs(rdArgs);
  1144.  
  1145.     /* Return -- no result */
  1146.     return(NULL);
  1147.  
  1148. }
  1149.  
  1150. STRPTR cdReadXL(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1151. {
  1152.  
  1153.     Printf("%s: Not yet implemented\n",PROGRAM_NAME);
  1154.  
  1155.     *error=RC_WARN;
  1156.     return(NULL);
  1157.  
  1158. }
  1159.  
  1160. /****** cd/cdRemChangeInt ******************************************
  1161. *
  1162. *   NAME
  1163. *       cdRemChangeInt -- remove frame interrupt
  1164. *
  1165. *   SYNOPSIS
  1166. *       result=cdRemChangeInt(rxMsg,args,error);
  1167. *
  1168. *       STRPTR cdRemChangeInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error);
  1169. *
  1170. *   FUNCTION
  1171. *       Remove disk change interrupt.
  1172. *
  1173. *   INPUTS
  1174. *       rxMsg   -   ARexx message
  1175. *       args    -   arguments from ARexx
  1176. *       error   -   pointer to error value
  1177. *
  1178. *   RESULT
  1179. *       *error  -   Error code (if any)
  1180. *       result  -   result string
  1181. *
  1182. *   EXAMPLE
  1183. *
  1184. *   NOTES
  1185. *
  1186. *   BUGS
  1187. *       Normal procedure for handling exec.library I/O requests
  1188. *       requires that an I/O request be completed before it is
  1189. *       re-used. However, for historical reasons, the *_ADDCHANGEINT
  1190. *       and *_ADDFRAMEINT commands of trackdisk.device, scsi.device,
  1191. *       and cd.device require the caller to send the I/O request
  1192. *       to add the interrupt and re-use the I/O request (without
  1193. *       calling exec.library/WaitIO()) with a *_REMCHANGEINT
  1194. *       or *_REMFRAMEINT command to remove the interrupt.
  1195. *
  1196. *       This causes IOTorture hits and is, in my humble opinion,
  1197. *       a Bad Thing(TM). However, it is apparently well beyond the
  1198. *       point where this behavior could be changed.
  1199. *
  1200. *   SEE ALSO
  1201. *       cdAddChangeInt
  1202. *
  1203. ******************************************************************************
  1204. *
  1205. */
  1206.  
  1207. STRPTR cdRemChangeInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1208. {
  1209.  
  1210.     BYTE ioError;
  1211.  
  1212.     /* Remove disk change interrupt */
  1213.     cdRequest->io_Command=CD_REMCHANGEINT;
  1214.     cdRequest->io_Length=sizeof(changeInterrupt);
  1215.     cdRequest->io_Data=&changeInterrupt;
  1216.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1217.     if (ioError) {
  1218.         if (debugMode) {
  1219.             printf("CD_REMCHANGEINT I/O error %d\n",ioError);
  1220.         }
  1221.         *error=RC_ERROR;
  1222.     }
  1223.  
  1224.     /* Return w/o result */
  1225.     return(NULL);
  1226.  
  1227. }
  1228.  
  1229. /****** cd/cdRemFrameInt ******************************************
  1230. *
  1231. *   NAME
  1232. *       cdRemFrameInt -- remove frame interrupt
  1233. *
  1234. *   SYNOPSIS
  1235. *       result=cdRemFrameInt(rxMsg,args,error);
  1236. *
  1237. *       STRPTR cdRemFrameInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error);
  1238. *
  1239. *   FUNCTION
  1240. *       Remove frame interrupt.
  1241. *
  1242. *   INPUTS
  1243. *       rxMsg   -   ARexx message
  1244. *       args    -   arguments from ARexx
  1245. *       error   -   pointer to error value
  1246. *
  1247. *   RESULT
  1248. *       *error  -   Error code (if any)
  1249. *       result  -   result string
  1250. *
  1251. *   EXAMPLE
  1252. *
  1253. *   NOTES
  1254. *
  1255. *   BUGS
  1256. *       Normal procedure for handling exec.library I/O requests
  1257. *       requires that an I/O request be completed before it is
  1258. *       re-used. However, for historical reasons, the *_ADDCHANGEINT
  1259. *       and *_ADDFRAMEINT commands of trackdisk.device, scsi.device,
  1260. *       and cd.device require the caller to send the I/O request
  1261. *       to add the interrupt and re-use the I/O request (without
  1262. *       calling exec.library/WaitIO()) with a *_REMCHANGEINT
  1263. *       or *_REMFRAMEINT command to remove the interrupt.
  1264. *
  1265. *       This causes IOTorture hits and is, in my humble opinion,
  1266. *       a Bad Thing(TM). However, it is apparently well beyond the
  1267. *       point where this behavior could be changed.
  1268. *
  1269. *   SEE ALSO
  1270. *       cdAddFrameInt
  1271. *
  1272. ******************************************************************************
  1273. *
  1274. */
  1275.  
  1276. STRPTR cdRemFrameInt(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1277. {
  1278.  
  1279.     BYTE ioError;
  1280.  
  1281.     /* Remove frame interrupt */
  1282.     cdRequest->io_Command=CD_REMFRAMEINT;
  1283.     cdRequest->io_Length=sizeof(frameInterrupt);
  1284.     cdRequest->io_Data=&frameInterrupt;
  1285.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1286.     if (ioError) {
  1287.         if (debugMode) {
  1288.             printf("CD_REMFRAMEINT I/O error %d\n",ioError);
  1289.         }
  1290.         *error=RC_ERROR;
  1291.     }
  1292.  
  1293.     /* Return w/o result */
  1294.     return(NULL);
  1295.  
  1296. }
  1297.  
  1298. STRPTR cdSearch(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1299. {
  1300.  
  1301.     static struct options {
  1302.         LONG normal;
  1303.         LONG ffwd;
  1304.         LONG frev;
  1305.     } options;
  1306.     struct RDArgs *rdArgs;
  1307.  
  1308.     BYTE ioError;
  1309.  
  1310.     /* Parse arguments */
  1311.     rdArgs=obtainArgs(args,"NORMAL/S,FFWD/S,FREV/S",
  1312.         &options,sizeof(options));
  1313.     if (!rdArgs) {
  1314.         *error=RC_ERROR;
  1315.         return(NULL);
  1316.     }
  1317.  
  1318.     /* Set search mode */
  1319.     cdRequest->io_Command=CD_SEARCH;
  1320.     if (options.normal) {
  1321.         cdRequest->io_Length=CDMODE_NORMAL;
  1322.     }
  1323.     if (options.ffwd) {
  1324.         cdRequest->io_Length=CDMODE_FFWD;
  1325.     }
  1326.     if (options.frev) {
  1327.         cdRequest->io_Length=CDMODE_FREV;
  1328.     }
  1329.     if (!(options.normal) & !(options.ffwd) & !(options.frev)) {
  1330.         cdRequest->io_Length=-1L;
  1331.     }
  1332.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1333.     if (ioError) {
  1334.         if (debugMode) {
  1335.             printf("CD_SEARCH I/O error %d\n",ioError);
  1336.         }
  1337.         *error=RC_ERROR;
  1338.     }
  1339.  
  1340.     /* Free argument parsing structure */
  1341.     releaseArgs(rdArgs);
  1342.  
  1343.     /* Return w/o result */
  1344.     return(NULL);
  1345.  
  1346. }
  1347.  
  1348. STRPTR cdSeek(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1349. {
  1350.  
  1351.     static struct options {
  1352.         LONG *offset;
  1353.     } options;
  1354.     struct RDArgs *rdArgs;
  1355.  
  1356.     BYTE ioError;
  1357.  
  1358.     /* Parse arguments */
  1359.     rdArgs=obtainArgs(args,"OFFSET/N/A",
  1360.         &options,sizeof(options));
  1361.     if (!rdArgs) {
  1362.         *error=RC_ERROR;
  1363.         return(NULL);
  1364.     }
  1365.  
  1366.     /* Seek */
  1367.     cdRequest->io_Command=CD_SEEK;
  1368.     cdRequest->io_Offset=*options.offset;
  1369.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1370.     if (ioError) {
  1371.         if (debugMode) {
  1372.             printf("CD_SEEK I/O error %d\n",ioError);
  1373.         }
  1374.         *error=RC_ERROR;
  1375.     }
  1376.  
  1377.     /* Free argument parsing structure */
  1378.     releaseArgs(rdArgs);
  1379.  
  1380.     /* Return w/o result */
  1381.     return(NULL);
  1382.  
  1383. }
  1384.  
  1385. STRPTR cdTOCLSN(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1386. {
  1387.  
  1388.     static struct options {
  1389.         STRPTR stem;
  1390.         LONG *entries;
  1391.         LONG *begin;
  1392.     } options;
  1393.     struct RDArgs *rdArgs;
  1394.  
  1395.     BYTE ioError;
  1396.  
  1397.     struct TOCEntry *buffer;
  1398.     struct TOCSummary *summary;
  1399.     int index;
  1400.  
  1401.     /* Parse arguments */
  1402.     rdArgs=obtainArgs(args,"STEM/A,ENTRIES/N/A,BEGIN/N/A",
  1403.         &options,sizeof(options));
  1404.     if (!rdArgs) {
  1405.         *error=RC_ERROR;
  1406.         return(NULL);
  1407.     }
  1408.  
  1409.     if (debugMode) {
  1410.         printf("cdTOCLSN -- Stem=%s, Entries=%ld, Begin=%ld\n",
  1411.             options.stem,*options.entries,*options.begin);
  1412.     }
  1413.  
  1414.     /* Allocate TOC buffer */
  1415.     buffer=AllocVec(sizeof(struct TOCEntry)*(*options.entries),MEMF_CLEAR);
  1416.     if (!buffer) {
  1417.         if (debugMode) {
  1418.             printf("Error allocating TOC buffer\n");
  1419.         }
  1420.         *error=RC_ERROR;
  1421.         return(NULL);
  1422.     }
  1423.  
  1424.     /* Fetch TOC in LSN format */
  1425.     cdRequest->io_Command=CD_TOCLSN;
  1426.     cdRequest->io_Data=buffer;
  1427.     cdRequest->io_Length=*options.entries;
  1428.     cdRequest->io_Offset=*options.begin;
  1429.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1430.     if (ioError) {
  1431.         if (debugMode) {
  1432.             printf("CD_TOCLSN I/O error %d",ioError);
  1433.         }
  1434.         *error=RC_ERROR;
  1435.     }
  1436.     if (debugMode) {
  1437.         printf("CD_TOCLSN good\n");
  1438.     }
  1439.  
  1440.     /* Return summary, if requested */
  1441.     if (*options.begin==0) {
  1442.  
  1443.         summary=(struct TOCSummary *) &(buffer[0]);
  1444.         setStemVarInt(rxMsg,options.stem,"Summary.FirstTrack",summary->FirstTrack);
  1445.         if (debugMode) {
  1446.             printf("    FirstTrack=%ld\n",summary->FirstTrack);
  1447.         }
  1448.         setStemVarInt(rxMsg,options.stem,"Summary.LastTrack",summary->LastTrack);
  1449.         if (debugMode) {
  1450.             printf("    LastTrack=%ld\n",summary->LastTrack);
  1451.         }
  1452.         setStemVarInt(rxMsg,options.stem,"Summary.LeadOut",summary->LeadOut.LSN);
  1453.         if (debugMode) {
  1454.             printf("    LeadOut=%ld\n",summary->LeadOut.LSN);
  1455.         }
  1456.  
  1457.     }
  1458.  
  1459.     /* Return TOC entries */
  1460.     for (index=(*options.begin==0)?1:0;
  1461.          index<(*options.entries);
  1462.          index++) {
  1463.         if (debugMode) {
  1464.             printf("Entry %d (detail for track %d)\n",index,buffer[index].Track);
  1465.         }
  1466.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1467.             "CtlAdr",buffer[index].CtlAdr);
  1468.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1469.             "Track",buffer[index].Track);
  1470.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1471.             "Position",buffer[index].Position.LSN);
  1472.     }
  1473.  
  1474.     /* Free argument parsing structure */
  1475.     releaseArgs(rdArgs);
  1476.  
  1477.     /* Return w/o result */
  1478.     return(NULL);
  1479.  
  1480. }
  1481.  
  1482. STRPTR cdTOCMSF(struct RexxMsg *rxMsg,STRPTR args,LONG *error)
  1483. {
  1484.  
  1485.     static struct options {
  1486.         STRPTR stem;
  1487.         LONG *entries;
  1488.         LONG *begin;
  1489.     } options;
  1490.     struct RDArgs *rdArgs;
  1491.  
  1492.     BYTE ioError;
  1493.  
  1494.     struct TOCEntry *buffer;
  1495.     struct TOCSummary *summary;
  1496.     int index;
  1497.  
  1498.     /* Parse arguments */
  1499.     rdArgs=obtainArgs(args,"STEM/A,ENTRIES/N/A,BEGIN/N/A",
  1500.         &options,sizeof(options));
  1501.     if (!rdArgs) {
  1502.         *error=RC_ERROR;
  1503.         return(NULL);
  1504.     }
  1505.  
  1506.     if (debugMode) {
  1507.         printf("cdTOCMSF -- Stem=%s, Entries=%ld, Begin=%ld\n",
  1508.             options.stem,*options.entries,*options.begin);
  1509.     }
  1510.  
  1511.     /* Allocate TOC buffer */
  1512.     buffer=AllocVec(sizeof(struct TOCEntry)*(*options.entries),MEMF_CLEAR);
  1513.     if (!buffer) {
  1514.         if (debugMode) {
  1515.             printf("Error allocating TOC buffer\n");
  1516.         }
  1517.         *error=RC_ERROR;
  1518.         return(NULL);
  1519.     }
  1520.  
  1521.     /* Fetch TOC in MSF format */
  1522.     cdRequest->io_Command=CD_TOCMSF;
  1523.     cdRequest->io_Data=buffer;
  1524.     cdRequest->io_Length=*options.entries;
  1525.     cdRequest->io_Offset=*options.begin;
  1526.     if (noCD) { ioError=-1; } else { ioError=DoIO(cdRequest); }
  1527.     if (ioError) {
  1528.         if (debugMode) {
  1529.             printf("CD_TOCMSF I/O error %d\n",ioError);
  1530.         }
  1531.         *error=RC_ERROR;
  1532.         *error=RC_ERROR;
  1533.     }
  1534.  
  1535.     /* Return summary, if requested */
  1536.     if (*options.begin==0) {
  1537.  
  1538.         summary=(struct TOCSummary *) &(buffer[0]);
  1539.         setStemVarInt(rxMsg,options.stem,"Summary.FirstTrack",summary->FirstTrack);
  1540.         if (debugMode) {
  1541.             printf("    FirstTrack=%ld\n",summary->FirstTrack);
  1542.         }
  1543.         setStemVarInt(rxMsg,options.stem,"Summary.LastTrack",summary->LastTrack);
  1544.         if (debugMode) {
  1545.             printf("    LastTrack=%ld\n",summary->LastTrack);
  1546.         }
  1547.         if (debugMode) {
  1548.             printf("    LeadOut=%02d:%02d:%02d\n",
  1549.                 summary->LeadOut.MSF.Minute,summary->LeadOut.MSF.Second,
  1550.                 summary->LeadOut.MSF.Frame);
  1551.         }
  1552.         setStemVarInt(rxMsg,options.stem,"Summary.LeadOut.Minute",
  1553.             summary->LeadOut.MSF.Minute);
  1554.         setStemVarInt(rxMsg,options.stem,"Summary.LeadOut.Second",
  1555.             summary->LeadOut.MSF.Second);
  1556.         setStemVarInt(rxMsg,options.stem,"Summary.LeadOut.Frame",
  1557.             summary->LeadOut.MSF.Frame);
  1558.  
  1559.     }
  1560.  
  1561.     /* Return TOC entries */
  1562.     for (index=(*options.begin==0)?1:0;
  1563.          index<*options.entries;
  1564.          index++) {
  1565.  
  1566.         if (debugMode) {
  1567.             printf("Entry %d (detail for track %d)\n",index,buffer[index].Track);
  1568.         }
  1569.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1570.             "CtlAdr",buffer[index].CtlAdr);
  1571.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1572.             "Track",buffer[index].Track);
  1573.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1574.             "Position.Minute",buffer[index].Position.MSF.Minute);
  1575.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1576.             "Position.Second",buffer[index].Position.MSF.Second);
  1577.         setStemVarIntArray(rxMsg,options.stem,buffer[index].Track,
  1578.             "Position.Frame",buffer[index].Position.MSF.Frame);
  1579.  
  1580.     }
  1581.  
  1582.     /* Free argument parsing structure */
  1583.     releaseArgs(rdArgs);
  1584.  
  1585.     /* Return w/o result */
  1586.     return(NULL);
  1587.  
  1588. }
  1589.